package com.luoke.manage.gamemanage;

import java.util.*;

public class GameManage {

    private static final double EPSILON = 1e-6;

    /**
     * 吃苹果游戏
     * @return
     */
    public String eatAppleGame() {
        Random rand = new Random();
        Scanner scan = new Scanner(System.in);
        int apple_num = rand.nextInt(100);
        System.out.println("一共有" + apple_num + "个苹果");
        boolean flag = true;
        String result = "";
        while (flag) {
            System.out.println("请选择你要吃掉的苹果数（可以选择两个或者3个）");
            int eat_num_player = scan.nextInt();
            apple_num = apple_num - eat_num_player;
            if (compare(apple_num)) System.out.println("你选择吃掉了" + apple_num + "个苹果,还剩下" + apple_num + "个");
            else {
                result = "恭喜你，你成功了";
                break;
            }

            int eat_num_system = rand.nextInt(2) + 2;
            apple_num = apple_num - eat_num_system;
            if (compare(apple_num)) System.out.println("系统吃掉了" + eat_num_system + "个苹果，还剩下" + apple_num);
            else {
                result = "不好意思，你失败了";
                break;
            }
        }
        return result;
    }

    /**
     * 走迷宫游戏
     * @return
     */
    public String mazeGame() {
        Scanner scanner = new Scanner(System.in);
        System.out.print("选择要生成的迷宫的大小(须大于等于5):");
        int size = scanner.nextInt();
        MazeGame mazeGame = new MazeGame(size);
        mazeGame.printMaze();
        while (true) {
            System.out.print("选择你的移动方向(w/s/a/d): ");
            char move = scanner.next().charAt(0);
            String result = mazeGame.movePlayer(move);
            if (result.contains("成功")) {
                return result;
            }
            mazeGame.printMaze();
        }
    }

    public static boolean compare(int num) {
        if (num <= 0) {
            return false;
        } else {
            return true;
        }
    }


    class MazeGame {
        private static final char WALL = '#';
        private static final char PATH = ' ';
        private static final char PLAYER = 'P';
        private static final char EXIT = 'E';

        private int size;
        private char[][] maze;
        private int playerRow, playerCol;
        private boolean[][] visited;
        private Random random = new Random();

        public MazeGame(int size) {
            this.size = size;
            this.maze = new char[size][size];
            this.visited = new boolean[size][size];

            boolean feasible = false;
            while (!feasible) {//确保迷宫的可行性
                initializeMaze();
                generateMaze(1, 1);
                placePlayer();
                placeExit();
                feasible = isMazeFeasible();
            }
        }

        private void initializeMaze() {//对迷宫初始化生成墙
            for (int i = 0; i < size; i++) {
                for (int j = 0; j < size; j++) {
                    maze[i][j] = WALL;
                    visited[i][j] = false;
                }
            }
        }

        private void generateMaze(int row, int col) {//使用深搜随机生成一个迷宫
            visited[row][col] = true;
            maze[row][col] = PATH;

            int[][] directions = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
            shuffleDirections(directions);

            for (int[] dir : directions) {
                int newRow = row + dir[0] * 2;
                int newCol = col + dir[1] * 2;

                if (isValid(newRow, newCol) && !visited[newRow][newCol]) {
                    maze[row + dir[0]][col + dir[1]] = PATH;
                    generateMaze(newRow, newCol);
                }
            }
        }

        private void shuffleDirections(int[][] directions) {//打乱墙的排序
            for (int i = directions.length - 1; i > 0; i--) {
                int index = random.nextInt(i + 1);
                int[] temp = directions[index];
                directions[index] = directions[i];
                directions[i] = temp;
            }
        }

        private boolean isValid(int row, int col) {
            return row > 0 && row < size - 1 && col > 0 && col < size - 1;
        }

        private void placePlayer() {//生成玩家出生点
            do {
                playerRow = random.nextInt(size - 2) + 1;
                playerCol = random.nextInt(size - 2) + 1;
            } while (maze[playerRow][playerCol] != PATH);
            maze[playerRow][playerCol] = PLAYER;
        }

        private void placeExit() {//生成出口
            int exitRow, exitCol;
            do {
                exitRow = random.nextInt(size - 2) + 1;
                exitCol = random.nextInt(size - 2) + 1;
            } while (maze[exitRow][exitCol] != PATH);
            maze[exitRow][exitCol] = EXIT;
        }

        private boolean isMazeFeasible() {//验证可行性
            Queue<int[]> queue = new LinkedList<>();
            boolean[][] visited = new boolean[size][size];
            int[][] directions = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};

            queue.add(new int[]{playerRow, playerCol});
            visited[playerRow][playerCol] = true;

            while (!queue.isEmpty()) {
                int[] current = queue.poll();
                int row = current[0];
                int col = current[1];

                if (maze[row][col] == EXIT) {
                    return true;
                }

                for (int[] dir : directions) {
                    int newRow = row + dir[0];
                    int newCol = col + dir[1];

                    if (isValid(newRow, newCol) && !visited[newRow][newCol] && maze[newRow][newCol] != WALL) {
                        visited[newRow][newCol] = true;
                        queue.add(new int[]{newRow, newCol});
                    }
                }
            }

            return false;
        }

        private void printMaze() {//打印迷宫
            for (int i = 0; i < size; i++) {
                for (int j = 0; j < size; j++) {
                    System.out.print(maze[i][j]);
                }
                System.out.println();
            }
        }

        private String movePlayer(char direction) {//控制玩家移动
            String result = "";
            int newRow = playerRow;
            int newCol = playerCol;

            switch (direction) {
                case 'w':
                    newRow--;
                    break;
                case 's':
                    newRow++;
                    break;
                case 'a':
                    newCol--;
                    break;
                case 'd':
                    newCol++;
                    break;
            }

            if (isValid(newRow, newCol) && maze[newRow][newCol] != WALL) {
                if (maze[newRow][newCol] == EXIT) {
                    System.out.println("恭喜你，成功走到终点");
                    result = "恭喜你，成功走到终点";
                    return result;
                }

                maze[playerRow][playerCol] = PATH;
                maze[newRow][newCol] = PLAYER;
                playerRow = newRow;
                playerCol = newCol;
            }
            return result;
        }
    }


    /**
     * 二十四点游戏
     * @return
     */
    public String twentyFourPointGame(){
        int count = 0; // 正确次数
        int wrongCount = 0; // 错误次数
        final int MAX_WRONG_COUNT = 3; // 最大错误次数

        Scanner scanner = new Scanner(System.in);

        while (true) {
            if (wrongCount >= MAX_WRONG_COUNT) {
                System.out.println("你已经连续答错 " + MAX_WRONG_COUNT + " 次，游戏结束！");
                return "失败";
            }

            Random random = new Random();

            // 生成4个随机数
            int[] numbers = new int[4];
            for (int i = 0; i < 4; i++) {
                numbers[i] = random.nextInt(13) + 1;
            }

            System.out.println("系统生成的数字是: " + Arrays.toString(numbers));

            // 判断是否能组成24点
            boolean possible = is24Possible(numbers);
            if (possible) {
                boolean correctAnswer = false;
                while (!correctAnswer) {
                    System.out.println("请判断是否可以组成24点（输入是或否,还剩"+(3-wrongCount)+"次机会):");
                    String answer = scanner.nextLine();
                    if (answer.equals("是")) {
                        System.out.println("请输入一个表达式（例如：(6+3)*(4-2)）：");
                        String expression = scanner.nextLine();
                        if (isValidExpression(expression, numbers)) {
                            try {
                                int result = evaluateExpression(expression);
                                if (result == 24) {
                                    System.out.println("正确！表达式结果为24。");
                                    count++;
                                    correctAnswer = true;
                                } else {
                                    System.out.println("答错！表达式结果不为24。");
                                    wrongCount++;
                                    if (wrongCount >= MAX_WRONG_COUNT) {
                                        System.out.println("你已经连续答错 " + MAX_WRONG_COUNT + " 次，游戏结束！");
                                        return "失败";
                                    }
                                    System.out.println("是否继续输入新的表达式（输入'是'或'否'）或者选择下一题（输入'下一题'）：");
                                    String choice = scanner.nextLine();
                                    if (choice.equals("否") || choice.equals("下一题")) {
                                        correctAnswer = true;
                                    }
                                }
                            } catch (Exception e) {
                                System.out.println("表达式计算错误: " + e.getMessage());
                                wrongCount++;
                                if (wrongCount >= MAX_WRONG_COUNT) {
                                    System.out.println("你已经连续答错 " + MAX_WRONG_COUNT + " 次，游戏结束！");
                                    return "失败";
                                }
                            }
                        } else {
                            System.out.println("输入的表达式无效。");
                            wrongCount++;
                            if (wrongCount >= MAX_WRONG_COUNT) {
                                System.out.println("你已经连续答错 " + MAX_WRONG_COUNT + " 次，游戏结束！");
                                return "失败";
                            }
                        }
                    } else if (answer.equals("否")) {
                        System.out.println("答错！这些数字可以组成24点。");
                        wrongCount++;
                        if (wrongCount >= MAX_WRONG_COUNT) {
                            System.out.println("你已经连续答错 " + MAX_WRONG_COUNT + " 次，游戏结束！");
                            return "失败";
                        }
                        correctAnswer = true;
                    } else {
                        System.out.println("无效输入。请输入'是'或'否'。");
                    }
                }
            } else {
                System.out.println("请判断是否可以组成24点（输入是或否,还剩"+(3-wrongCount)+"次机会):");
                String answer = scanner.nextLine();
                if (answer.equals("是")) {
                    System.out.println("答错！这些数字不能组成24点。");
                    wrongCount++;
                    if (wrongCount >= MAX_WRONG_COUNT) {
                        System.out.println("你已经连续答错 " + MAX_WRONG_COUNT + " 次，游戏结束!你一共答对了"+count+"次！");
                        return "失败";
                    }
                } else if (answer.equals("否")) {
                    System.out.println("正确！这些数字不能组成24点。");
                    count++;
                } else {
                    System.out.println("无效输入。请输入'是'或'否'。");
                }
            }

            System.out.println("\n是否继续游戏？（输入'是'或'否'）");
            String continueGame = scanner.nextLine();
            if (continueGame.equals("否")) {
                System.out.println("你赢得了 " + count + " 次");
                return "成功"+count;
            } else if (!continueGame.equals("是")) {
                System.out.println("无效输入。默认继续游戏。");
            }
        }
    }


    // 判断是否可以组成24点
    private static boolean is24Possible(int[] numbers) {
        List<Double> nums = new ArrayList<>();
        for (int num : numbers) {
            nums.add((double) num);
        }
        return solve(nums);
    }

    private static boolean solve(List<Double> nums) {
        if (nums.size() == 1) {
            return Math.abs(nums.get(0) - 24) < EPSILON;
        }

        for (int i = 0; i < nums.size(); i++) {
            for (int j = 0; j < nums.size(); j++) {
                if (i != j) {
                    List<Double> nextNums = new ArrayList<>();
                    for (int k = 0; k < nums.size(); k++) {
                        if (k != i && k != j) {
                            nextNums.add(nums.get(k));
                        }
                    }
                    for (int op = 0; op < 4; op++) {
                        if (op < 2 && j > i) continue;
                        if (op == 0) nextNums.add(nums.get(i) + nums.get(j));
                        if (op == 1) nextNums.add(nums.get(i) * nums.get(j));
                        if (op == 2) nextNums.add(nums.get(i) - nums.get(j));
                        if (op == 3) {
                            if (Math.abs(nums.get(j)) < EPSILON) continue;
                            nextNums.add(nums.get(i) / nums.get(j));
                        }

                        if (solve(nextNums)) return true;
                        nextNums.remove(nextNums.size() - 1);
                    }
                }
            }
        }
        return false;
    }

    private static boolean isValidExpression(String expression, int[] numbers) {
        Set<Integer> uniqueNumbers = new HashSet<>();
        for (int num : numbers) {
            uniqueNumbers.add(num);
        }

        String cleanExpression = expression.replaceAll("[^0-9]", " ");
        String[] tokens = cleanExpression.split("\\s+");
        Map<Integer, Integer> countMap = new HashMap<>();
        for (String token : tokens) {
            if (!token.isEmpty()) {
                try {
                    int value = Integer.parseInt(token);
                    countMap.put(value, countMap.getOrDefault(value, 0) + 1);
                } catch (NumberFormatException e) {
                    return false;
                }
            }
        }

        for (int num : uniqueNumbers) {
            if (!countMap.containsKey(num) || countMap.get(num) != 1) {
                return false;
            }
        }

        return true;
    }

    public static int evaluateExpression(String expression) {
        expression = expression.replaceAll("\\s+", "");
        return evaluate(expression);
    }

    private static int evaluate(String expression) {
        Stack<Integer> values = new Stack<>();
        Stack<Character> operators = new Stack<>();

        int i = 0;
        while (i < expression.length()) {
            char ch = expression.charAt(i);

            if (Character.isDigit(ch)) {
                int num = 0;
                while (i < expression.length() && Character.isDigit(expression.charAt(i))) {
                    num = num * 10 + (expression.charAt(i) - '0');
                    i++;
                }
                values.push(num);
                continue;
            } else if (ch == '(') {
                operators.push(ch);
            } else if (ch == ')') {
                while (!operators.isEmpty() && operators.peek() != '(') {
                    values.push(applyOperator(operators.pop(), values.pop(), values.pop()));
                }
                operators.pop();
            } else if (isOperator(ch)) {
                while (!operators.isEmpty() && precedence(operators.peek()) >= precedence(ch)) {
                    values.push(applyOperator(operators.pop(), values.pop(), values.pop()));
                }
                operators.push(ch);
            }
            i++;
        }

        while (!operators.isEmpty()) {
            values.push(applyOperator(operators.pop(), values.pop(), values.pop()));
        }

        return values.pop();
    }

    private static boolean isOperator(char ch) {
        return ch == '+' || ch == '-' || ch == '*' || ch == '/';
    }

    private static int precedence(char operator) {
        if (operator == '+' || operator == '-') return 1;
        if (operator == '*' || operator == '/') return 2;
        return 0;
    }

    private static int applyOperator(char operator, int b, int a) {
        switch (operator) {
            case '+':
                return a + b;
            case '-':
                return a - b;
            case '*':
                return a * b;
            case '/':
                if (b == 0) throw new ArithmeticException("除以零错误");
                return a / b;
        }
        throw new IllegalArgumentException("无效运算符:" + operator);
    }



}
